var fs = require('fs');
var Iconv = require('iconv').Iconv;

var spliter = '\t';

function parseDate(strDate){
    // 2013:8:7:14:0:0
    if( typeof(strDate) != 'string' ) {
        return 0;
    }

    var segs = strDate.split(':'); 
    if( 6 == segs.length ) {
        // 获取活动开始和结束的时间(秒)
        var date = new Date(segs[0],+segs[1]-1,segs[2],segs[3],segs[4],segs[5]);
        return Math.floor(date.getTime()/1000); 
    }else{
        ERROR('parseDate invalid date:'+strDate);
    }

    return 0;
}

function CommonCSV(name, indexs) {
    var converter = new Iconv('GBK', 'UTF8');
    var rawData = converter.convert(fs.readFileSync(name)).toString();

    indexs = indexs || [];

    var rows = rawData.split('\n');
    var columns = rows[1].split(spliter);
    for(var j=0; j<columns.length; j++ ) {
        columns[j] = columns[j].trim();
    }

    for( var i=2; i<rows.length; i++ ) {
        if( rows[i].trim().length == 0 ) {
            continue;
        }
        var cols = rows[i].split(spliter);
        if( cols.length != columns.length ){
            ERROR('invalid csv ' + name + ' at line: ' + i);
            continue;
        }

        var obj = {};
        for(var j=0; j<cols.length; j++ ) {
            var column = columns[j];
            var value = cols[j].trim();
            if (/^Award\d*$/.test(column) || /^Award_\d*$/.test(column) || /^Award[a-zA-Z]{2,}\d*$/.test(column)) {
                // 单个奖励
                var segs = value.split(':');
                if( 2 == segs.length ){
                    value = segs[0].split('.');
                    value.push(+segs[1]);
                }else{
                    value = null;
                }
            }else if( /^Awards\d*$/.test(column) || /^Awards_\d*$/.test(column) ) {
                // 多个奖励
                var awards = [];
                var strAwards = value.split('|');
                strAwards.forEach(function(strAward){
                    var segs = strAward.split(':');
                    if( 2 == segs.length ){
                        var award = segs[0].split('.');
                        award.push(+segs[1]);
                        awards.push(award);
                    }
                });

                value = awards;
            }

            if( !isNaN(value) ) {
                value = +value;
            }
            obj[column] = value;
        }
        var data = this;
        for( var k=0; k<indexs.length-1; k++ ) {
            var index = indexs[k];
            if( !(obj[index] in data) ) {
                data[obj[index]] = {}; 
            }
            data = data[obj[index]];
        }

        var lastIndex = indexs[indexs.length-1];
        data[obj[lastIndex]] = obj;
    }
}

function GlobalCSV(name) {
    var rawData = fs.readFileSync(name, 'utf8');

    var rows = rawData.split('\n');
    for( var i=2; i<rows.length; i++ ) {
        if( rows[i].trim().length == 0 ) {
            continue;
        }
        var cols = rows[i].split(spliter);
        if( cols.length != 3 ) {
            ERROR('invalid global csv ' + name + ' at ' + i);
            continue;
        }
        var key = cols[1];
        var value = cols[2].trim();

        if( !isNaN(value) ) {
            value = +value;
        }
        
        // 装备初始宝石配置 gid1:gid2
        if( key.endWith('GemSlot') ) {
            value = value.split(':');
            for( var j=0; j<value.length; j++ ) {
                value[j] = +value[j];
            }
        }

        this[key] = value;
    }
}

function SwitchCSV(name) {
    var rawData = fs.readFileSync(name, 'utf8');

    var rows = rawData.split('\n');
    for (var i=2; i<rows.length; ++i) {
        if (rows[i].trim().length == 0) {
            continue;
        }

        var cols = rows[i].split(spliter);
        if (cols.length != 3) {
            ERROR('invalid csv ' + name + ' at ' + i);
            continue;
        }

        var key = cols[1];
        var value = cols[2].trim();

        if (!isNaN(value)) {
            value = +value;
        }

        this[key] = value;
    }
}

function RoleCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);

    var rolesByQuantity = {};  
    var rolesByReceiveMode = {};
    var rolesByQuantityAndReceiveMode = {};
    var orangeRole = {};

    for(var id in csv ) {
        if(1 != csv[id]['Period']){
            continue;
        }

        this[id] = csv[id];

        //grouped by color
        var quantity = csv[id].Quantity;
        if( !(quantity in rolesByQuantity) ) {
            rolesByQuantity[quantity] = [];
        }
        rolesByQuantity[quantity].push(+id);
        
        //grouped by ReceiveMod
        var receiveMode = csv[id].ReceiveMode;
        if( !(receiveMode in rolesByReceiveMode) ){
            rolesByReceiveMode[receiveMode] = [];
        }

        rolesByReceiveMode[receiveMode].push(+id);
        
        //grouped by color and ReceiveMod
        if( !(quantity in rolesByQuantityAndReceiveMode) ) {
            rolesByQuantityAndReceiveMode[quantity] = {}; 
        } 

        if( !(receiveMode in rolesByQuantityAndReceiveMode[quantity]) ) {
             rolesByQuantityAndReceiveMode[quantity][receiveMode] = []; 
        }

        rolesByQuantityAndReceiveMode[quantity][receiveMode].push(+id);

        if( quantity == 'orange' && csv[id].hasOwnProperty('ReceiveWeight') && csv[id].ReceiveWeight) {
            // 橙将概率
            orangeRole[id] = csv[id].ReceiveWeight;
        }
    }
    
    this.rolesByQuantity = rolesByQuantity;
    this.rolesByReceiveMode = rolesByReceiveMode;
    this.rolesByQuantityAndReceiveMode = rolesByQuantityAndReceiveMode;

    if( Object.keys(orangeRole).length > 0 ) {
        this.orangeRole = orangeRole;
        var orangeSpecialRole = {};
        for( var rid in orangeRole ) {
            var weight = orangeRole[rid];
            if( weight >= 0 ) {
                orangeSpecialRole[rid] = weight;
            }
        }

        this.orangeSpecialRole = orangeSpecialRole;
    }
}

function TavernCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var level in csv ) {
        var rowObj = csv[level];
        rowObj.roles = {
            'white': rowObj.White,
            'blue': rowObj.Blue,
            'purple': rowObj.Purple,
            'orange': rowObj.Orange
        };
        this[level] = rowObj;
    }
}

function DailyTaskCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        this[id] = rowObj;
        this[rowObj.Action] = id;   //任务操作名字对应Id
    }
}

function BusinessCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        for( var i=1; i<=8; i++ ) {
            var gems = rowObj['Gem'+i].split(':');
            for( var j=0; j<gems.length; j++ ) {
                gems[j] = +gems[j];
            }
            rowObj['Gem'+i] = gems;
        }

        if( rowObj.GemFinal ) {
            var gems = rowObj.GemFinal.split(':');
            for( var j=0; j<gems.length; j++ ) {
                gems[j] = +gems[j];
            }

            rowObj.GemFinal = gems;
        }

        this[id] = rowObj;
    }
}

function CombineCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        for( var i=1; i<=2; i++ ) {
            var gems = rowObj['Gem'+i].split(':');
            for( var j=0; j<gems.length; j++ ) {
                gems[j] = +gems[j];
            }
            rowObj['Gem'+i] = gems;
        }
        this[id] = rowObj;
    }
}

function ActivityCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        rowObj.StartTime = parseDate(rowObj.StartTime);
        rowObj.EndTime = parseDate(rowObj.EndTime);
        rowObj.OpenTime = parseDate(rowObj.OpenTime);
        this[id] = rowObj;
    }
}

function AvCrazySendCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        this[id] = rowObj.Weight;
    }
}

function AvWesternCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        for( var i=1; i<=8; i++ ) {
            if( rowObj['Reward'+i][0] == '"' ) {
                // 去掉字符串首尾的" 符号
                var awards = rowObj['Reward'+i].slice(1,-1);
            }else {
                var awards = rowObj['Reward'+i];
            }

            awards = awards.split(",");
            var values = [];
            for( var j=0, len=awards.length; j<len; j++ ) {
                var segs = awards[j].split(':');
                var value = null;
                if( 2 == segs.length ){
                    value = segs[0].split('.');
                    value.push(+segs[1]);
                }                

                values.push(value);
            }

            rowObj['Reward'+i] = values;
        }
        this[id] = rowObj;
    }
}

function PVECSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        var petSkillLevels = "" + rowObj.PetSkillLevels;
        var skillLevels = {};
        // 新加字段为技能释放顺序数组
        rowObj.PetSkills = []; 
        if( !petSkillLevels ) {
            rowObj.petSkillLevels = skillLevels;      
            this[id] = rowObj;
            continue; 
        }

        petSkillLevels = petSkillLevels.split(':');
        for( var i = 0, len = petSkillLevels.length; i < len; i++  ) {
            var petSkillLevel = petSkillLevels[i].split('.'); 
            if( petSkillLevel.length != 2 || isNaN(petSkillLevel[0]) || isNaN(petSkillLevel[1]) ) {
                rowObj.petSkillLevels = skillLevels;      
                this[id] = rowObj;
                continue; 
            }
             
            skillLevels[+petSkillLevel[0]] = +petSkillLevel[1];
            rowObj.PetSkills.push(+petSkillLevel[0]);
        }

        rowObj.PetSkillLevels = skillLevels;

        this[id] = rowObj;
    }
}

function CloudShopCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var id in csv ) {
        var rowObj = csv[id];
        if( rowObj.CloudType == 2 ) {
            // 时限: a|b:c|d
            var ids = [];
            var segs = rowObj.Sell.split(":");
            segs.forEach(function(seg){
                ids.push(seg.split("|"));
            });
            rowObj.Sell = ids;
        }else if( rowObj.CloudType == 1 ) {
            // 人气: a|b|c|d
            rowObj.Sell = rowObj.Sell.split("|");
        }
        this[id] = rowObj;
    }
}

function TOWERCSV(name, indexs) {
    var csv = new CommonCSV(name, indexs);
    for( var towerId in csv ) {
        var towerCsv = csv[towerId];
        for( var id in towerCsv ) {
            var rowObj = towerCsv[id];
            var petSkillLevels = rowObj.PetSkillLevels;
            var skillLevels = {};
            // 新加字段为技能释放顺序数组
            rowObj.PetSkills = []; 
            if( !(towerId in this) ) {
                this[towerId] = {}; 
            }

            if( !petSkillLevels ) {
                rowObj.petSkillLevels = skillLevels;      
                this[towerId][id] = rowObj;
                continue; 
            }

            petSkillLevels = petSkillLevels.split(':');
            for( var i = 0, len = petSkillLevels.length; i < len; i++  ) {
                var petSkillLevel = petSkillLevels[i].split('.'); 
                if( petSkillLevel.length != 2 || isNaN(petSkillLevel[0]) || isNaN(petSkillLevel[1]) ) {
                    rowObj.petSkillLevels = skillLevels;      
                    this[id] = rowObj;
                    continue; 
                }
                 
                skillLevels[+petSkillLevel[0]] = +petSkillLevel[1];
                rowObj.PetSkills.push(+petSkillLevel[0]);
            }

            rowObj.PetSkillLevels = skillLevels;

            this[towerId][id] = rowObj;
        }
    }
}

exports.CommonCSV = CommonCSV;
exports.GlobalCSV = GlobalCSV;
exports.SwitchCSV = SwitchCSV;
exports.RoleCSV = RoleCSV;
exports.TavernCSV = TavernCSV;
exports.DailyTaskCSV = DailyTaskCSV;
exports.BusinessCSV = BusinessCSV;
exports.CombineCSV = CombineCSV;
exports.ActivityCSV = ActivityCSV;
exports.AvCrazySendCSV = AvCrazySendCSV;
exports.parseDate = parseDate;
exports.AvWesternCSV = AvWesternCSV;
exports.PVECSV = PVECSV;
exports.CloudShopCSV = CloudShopCSV;
exports.TOWERCSV = TOWERCSV;
